Trò chơi Tic-Tac-Toe, game đánh caro full source code
- ThirdPersonCamera.cs
- Player /
- Game /
- Scripts /
- DemoWorker /
- Demos /
- Photon Unity Networking /
- Assets /
- project /
2 using System.Collections;
3
4 public class ThirdPersonCamera : MonoBehaviour
5 {
6
7 public Transform cameraTransform;
8 private Transform _target;
9
10 // The distance in the x-z plane to the target
11
12 public float distance = 7.0f;
13
14 // the height we want the camera to be above the target
15 public float height = 3.0f;
16
17 public float angularSmoothLag = 0.3f;
18 public float angularMaxSpeed = 15.0f;
19
20 public float heightSmoothLag = 0.3f;
21
22 public float snapSmoothLag = 0.2f;
23 public float snapMaxSpeed = 720.0f;
24
25 public float clampHeadPositionScreenSpace = 0.75f;
26
27 public float lockCameraTimeout = 0.2f;
28
29 private Vector3 headOffset = Vector3.zero;
30 private Vector3 centerOffset = Vector3.zero;
31
32 private float heightVelocity = 0.0f;
33 private float angleVelocity = 0.0f;
34 private bool snap = false;
35 private ThirdPersonController controller;
36 private float targetHeight = 100000.0f;
37
38 private Camera m_CameraTransformCamera;
39
40 void OnEnable()
41 {
42 if( !cameraTransform && Camera.main )
43 cameraTransform = Camera.main.transform;
44 if( !cameraTransform )
45 {
46 Debug.Log( "Please assign a camera to the ThirdPersonCamera script." );
47 enabled = false;
48 }
49
50 m_CameraTransformCamera = cameraTransform.GetComponent<Camera>();
51
52 _target = transform;
53 if( _target )
54 {
55 controller = _target.GetComponent<ThirdPersonController>();
56 }
57
58 if( controller )
59 {
60 CharacterController characterController = (CharacterController)_target.GetComponent<Collider>();
61 centerOffset = characterController.bounds.center - _target.position;
62 headOffset = centerOffset;
63 headOffset.y = characterController.bounds.max.y - _target.position.y;
64 }
65 else
66 Debug.Log( "Please assign a target to the camera that has a ThirdPersonController script attached." );
67
68
69 Cut( _target, centerOffset );
70 }
71
72 void DebugDrawStuff()
73 {
74 Debug.DrawLine( _target.position, _target.position + headOffset );
75
76 }
77
78 float AngleDistance( float a, float b )
79 {
80 a = Mathf.Repeat( a, 360 );
81 b = Mathf.Repeat( b, 360 );
82
83 return Mathf.Abs( b - a );
84 }
85
86 void Apply( Transform dummyTarget, Vector3 dummyCenter )
87 {
88 // Early out if we don't have a target
89 if( !controller )
90 return;
91
92 Vector3 targetCenter = _target.position + centerOffset;
93 Vector3 targetHead = _target.position + headOffset;
94
95 // DebugDrawStuff();
96
97 // Calculate the current & target rotation angles
98 float originalTargetAngle = _target.eulerAngles.y;
99 float currentAngle = cameraTransform.eulerAngles.y;
100
101 // Adjust real target angle when camera is locked
102 float targetAngle = originalTargetAngle;
103
104 // When pressing Fire2 (alt) the camera will snap to the target direction real quick.
105 // It will stop snapping when it reaches the target
106 if( Input.GetButton( "Fire2" ) )
107 snap = true;
108
109 if( snap )
110 {
111 // We are close to the target, so we can stop snapping now!
112 if( AngleDistance( currentAngle, originalTargetAngle ) < 3.0f )
113 snap = false;
114
115 currentAngle = Mathf.SmoothDampAngle( currentAngle, targetAngle, ref angleVelocity, snapSmoothLag, snapMaxSpeed );
116 }
117 // Normal camera motion
118 else
119 {
120 if( controller.GetLockCameraTimer() < lockCameraTimeout )
121 {
122 targetAngle = currentAngle;
123 }
124
125 // Lock the camera when moving backwards!
126 // * It is really confusing to do 180 degree spins when turning around.
127 if( AngleDistance( currentAngle, targetAngle ) > 160 && controller.IsMovingBackwards() )
128 targetAngle += 180;
129
130 currentAngle = Mathf.SmoothDampAngle( currentAngle, targetAngle, ref angleVelocity, angularSmoothLag, angularMaxSpeed );
131 }
132
133
134 // When jumping don't move camera upwards but only down!
135 if( controller.IsJumping() )
136 {
137 // We'd be moving the camera upwards, do that only if it's really high
138 float newTargetHeight = targetCenter.y + height;
139 if( newTargetHeight < targetHeight || newTargetHeight - targetHeight > 5 )
140 targetHeight = targetCenter.y + height;
141 }
142 // When walking always update the target height
143 else
144 {
145 targetHeight = targetCenter.y + height;
146 }
147
148 // Damp the height
149 float currentHeight = cameraTransform.position.y;
150 currentHeight = Mathf.SmoothDamp( currentHeight, targetHeight, ref heightVelocity, heightSmoothLag );
151
152 // Convert the angle into a rotation, by which we then reposition the camera
153 Quaternion currentRotation = Quaternion.Euler( 0, currentAngle, 0 );
154
155 // Set the position of the camera on the x-z plane to:
156 // distance meters behind the target
157 cameraTransform.position = targetCenter;
158 cameraTransform.position += currentRotation * Vector3.back * distance;
159
160 // Set the height of the camera
161 cameraTransform.position = new Vector3( cameraTransform.position.x, currentHeight, cameraTransform.position.z );
162
163 // Always look at the target
164 SetUpRotation( targetCenter, targetHead );
165 }
166
167 void LateUpdate()
168 {
169 Apply( transform, Vector3.zero );
170 }
171
172 void Cut( Transform dummyTarget, Vector3 dummyCenter )
173 {
174 float oldHeightSmooth = heightSmoothLag;
175 float oldSnapMaxSpeed = snapMaxSpeed;
176 float oldSnapSmooth = snapSmoothLag;
177
178 snapMaxSpeed = 10000;
179 snapSmoothLag = 0.001f;
180 heightSmoothLag = 0.001f;
181
182 snap = true;
183 Apply( transform, Vector3.zero );
184
185 heightSmoothLag = oldHeightSmooth;
186 snapMaxSpeed = oldSnapMaxSpeed;
187 snapSmoothLag = oldSnapSmooth;
188 }
189
190 void SetUpRotation( Vector3 centerPos, Vector3 headPos )
191 {
192 // Now it's getting hairy. The devil is in the details here, the big issue is jumping of course.
193 // * When jumping up and down we don't want to center the guy in screen space.
194 // This is important to give a feel for how high you jump and avoiding large camera movements.
195 //
196 // * At the same time we dont want him to ever go out of screen and we want all rotations to be totally smooth.
197 //
198 // So here is what we will do:
199 //
200 // 1. We first find the rotation around the y axis. Thus he is always centered on the y-axis
201 // 2. When grounded we make him be centered
202 // 3. When jumping we keep the camera rotation but rotate the camera to get him back into view if his head is above some threshold
203 // 4. When landing we smoothly interpolate towards centering him on screen
204 Vector3 cameraPos = cameraTransform.position;
205 Vector3 offsetToCenter = centerPos - cameraPos;
206
207 // Generate base rotation only around y-axis
208 Quaternion yRotation = Quaternion.LookRotation( new Vector3( offsetToCenter.x, 0, offsetToCenter.z ) );
209
210 Vector3 relativeOffset = Vector3.forward * distance + Vector3.down * height;
211 cameraTransform.rotation = yRotation * Quaternion.LookRotation( relativeOffset );
212
213 // Calculate the projected center position and top position in world space
214 Ray centerRay = m_CameraTransformCamera.ViewportPointToRay( new Vector3( 0.5f, 0.5f, 1 ) );
215 Ray topRay = m_CameraTransformCamera.ViewportPointToRay( new Vector3( 0.5f, clampHeadPositionScreenSpace, 1 ) );
216
217 Vector3 centerRayPos = centerRay.GetPoint( distance );
218 Vector3 topRayPos = topRay.GetPoint( distance );
219
220 float centerToTopAngle = Vector3.Angle( centerRay.direction, topRay.direction );
221
222 float heightToAngle = centerToTopAngle / ( centerRayPos.y - topRayPos.y );
223
224 float extraLookAngle = heightToAngle * ( centerRayPos.y - centerPos.y );
225 if( extraLookAngle < centerToTopAngle )
226 {
227 extraLookAngle = 0;
228 }
229 else
230 {
231 extraLookAngle = extraLookAngle - centerToTopAngle;
232 cameraTransform.rotation *= Quaternion.Euler( -extraLookAngle, 0, 0 );
233 }
234 }
235
236 Vector3 GetCenterOffset()
237 {
238 return centerOffset;
239 }
240
241 }
The distance in the x-z plane to the target
the height we want the camera to be above the target
Early out if we don't have a target
DebugDrawStuff();
Calculate the current & target rotation angles
Adjust real target angle when camera is locked
When pressing Fire2 (alt) the camera will snap to the target direction real quick.
It will stop snapping when it reaches the target
We are close to the target, so we can stop snapping now!
Normal camera motion
Lock the camera when moving backwards!
* It is really confusing to do 180 degree spins when turning around.
When jumping don't move camera upwards but only down!
We'd be moving the camera upwards, do that only if it's really high
When walking always update the target height
Damp the height
Convert the angle into a rotation, by which we then reposition the camera
Set the position of the camera on the x-z plane to:
distance meters behind the target
Set the height of the camera
Always look at the target
Now it's getting hairy. The devil is in the details here, the big issue is jumping of course.
* When jumping up and down we don't want to center the guy in screen space.
This is important to give a feel for how high you jump and avoiding large camera movements.
* At the same time we dont want him to ever go out of screen and we want all rotations to be totally smooth.
So here is what we will do:
1. We first find the rotation around the y axis. Thus he is always centered on the y-axis
2. When grounded we make him be centered
3. When jumping we keep the camera rotation but rotate the camera to get him back into view if his head is above some threshold
4. When landing we smoothly interpolate towards centering him on screen
Generate base rotation only around y-axis
Calculate the projected center position and top position in world space